#ifndef __OE_MATH_TYPES_HEADER__
#define __OE_MATH_TYPES_HEADER__

/////////////////////////////////////////////////////////////////////
// Standard include files
#include <string>
#include <vector>
#include <cmath>

/////////////////////////////////////////////////////////////////////
// User-Defined include files

namespace OE
{
    template<class RealType>
    struct OEVector
    {
        () : x(0), y(0), z(0) { };
        OEVector(RealType xv, RealType yv, RealType zv)
        : x(xv), y(yv), z(zv) { };
        
        RealType x () { return x; };
        RealType y () { return y; };
        RealType z () { return z; };
        
        void setX (RealType xv) { x = xv; };
        void setY (RealType yv) { y = yv; };
        void setZ (RealType zv) { z = zv; };
        
        RealType length () 
        {
            return std::sqrt (x*x + y*y + z*z);
        };
        
        OEVector& normalize () 
        {
            RealType len = length();
            x /= len; y /= len; z /= len;
            return *this;
        };
        
        OEVector& scale (RealType scaleFactor)
        {
            x*=scaleFactor;
            y*=scaleFactor;
            z*=scaleFactor;
            return *this;
        };
        
        RealType dot (const OEVector& ov)
        {
            return (x*ov.x + y*ov.y + z*ov.z);
        };
        
        OEVector cross (const OEVector& ov)
        {
            OEVector retv;
            retv.x = y*ov.z - z*ov.y;
            retv.y = z*ov.x - x*ov.z;
            retv.z = x*ov.y - y*ov.x;
            return retv;
        };
        
        OEVector project (OEVector ov)
        {
            OEVector retVec=ov.normalize()
            return retVec.scale(length());
        };
        
        OEBool isNull () { return x == 0 && y == 0 && z == 0; };
        OEBool isEqual (const OEVector& ov) { return x==ov.x && y == ov.y && z == ov.z; };
        OEBool isParallel (const OEVector& ov) { return cross (ov) == 0.0; };
        OEBool isPerpendicular (const OEVector& ov) { return dot (ov) == 0.0; };
        
        // operator overloads
        void            operator = (const OEVector& ov) { x= ov.x; y = ov.y; z = ov.z; };
        RealType        operator * (const OEVector& ov) { dot(ov); };
        OEVector        operator * (RealType val) { scale(val); }
        OEBool          operator == (const OEVector& ov) { return isEqual(ov); };
        RealType        operator - (const OEVector& ov) { return OEVector(x-ov.x,y-ov.y,z-ov.z).length(); };
        
    private:
        RealType x, y, z;
    };
    
    typedef OEVector<OEReal32> OEReal32Vector;
    typedef OEVector<OEReal64> OEReal64Vector;
    
    typedef std::vector<OEReal32Vector> OEReal32VectorSeq;
    typedef std::vector<OEReal64Vector> OEReal64VectorSeq;
};

#endif /* __OE_MATH_TYPES_HEADER__ */
